﻿using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Chimp.Core;
namespace SpaceChimpIDE
{
   
    public partial class ChimpJointDoc : UserControl
    {
        public List<Keyword> Words = new List<Keyword>();
        public string DocPath { get; set; }
        public CodeComplete CC = null;
        public int ActiveSI = 0;
        public int ActiveEI = 0;
        public string GetText()
        {
            return EditArea.Text;
        }
        public ChimpJointDoc ( )
        {
            InitializeComponent ( );
            DocPath = "";
            NewWord("State",Color.DarkTurquoise);
            NewWord("Event",Color.Blue);
            NewWord("End",Color.Blue);
            NewWord("If",Color.DarkRed);
            NewWord("Else", Color.DarkRed);
            NewWord("ElseIf", Color.DarkRed);
            NewWord("BeginTransient",Color.DarkViolet);
            NewWord("StopTransient",Color.DarkTurquoise);
            NewWord("Number",Color.LightCyan);
            NewWord("String",Color.Red);
            NewWord("Transient",Color.DarkTurquoise);
            NewWord("DebugMessage",Color.DarkSlateGray);
            NewWord("Create", Color.Maroon);
            NewWord("=",Color.DarkMagenta);
            NewWord("+",Color.DarkMagenta);
            NewWord("*",Color.DarkMagenta);
            NewWord("/",Color.DarkMagenta);
            NewWord("-",Color.DarkMagenta);
            NewWord("~",Color.ForestGreen,".");
            NewWord("~",Color.Indigo,"~",".");
            NewWord("Static", Color.DodgerBlue);
            NewWord("Var", Color.MediumOrchid);
            NewWord("Float", Color.Red);
            NewWord("Int", Color.Red);
            NewWord("Bool", Color.DarkViolet);

            CC = new CodeComplete();
            CC.Show();
            CC.Hide();
        }
        public void NewWord(string k,Color w,params string[] o)
        {
            Words.Add(new Keyword(k,w,o));
        }
        public void HighlightDoc()
        {
            if ( AutoLight == false ) return;
           // AutoLight = false;

            Highlight(0,EditArea.TextLength);
            
           
        }
        public void Save()
        {
            if ( DocPath == "" ) return;
            FileStream fs= new FileStream(DocPath,FileMode.Create,FileAccess.Write);
            TextWriter w = new StreamWriter(fs);
            foreach(var l in EditArea.Lines)
            {
                w.WriteLine(l);
            }
            w.Flush();
            fs.Flush();
            w = null;
            fs = null;

        }
        public void Load(string p)
        {
            DocPath = p;
            var code = "";
            FileStream fs = new FileStream(DocPath,FileMode.Open,FileAccess.Read);
            TextReader r = new StreamReader(fs);
            //while(fs.Position<fs.Length)
            //{
                //code+=
            //}
            code += r.ReadToEnd();

            code += "\n";
            AutoLight = false;
            EditArea.Text = code;
            AutoLight = true;

            // HighlightDoc();

        }
        public void Highlight(int s1,int s2)
        {
            if ( s1 < 0 ) s1 = 0;
            if ( s2 < s1 + 1 ) s2 = s1 + 1;
            if ( s2 > EditArea.TextLength ) return;
            int sl = s2 - s1;
            int oi = EditArea.SelectionStart;
            int ol = EditArea.SelectionLength;
         

            EditArea.Select(s1,sl);
          
            var text = EditArea.SelectedText;
          
            string ptok = "";
            JointNode jn = new JointNode(text,"");
            while(jn._i<sl)
            {
                int si = jn._i;
                
                string tok = jn.GetTok();
                string ntok = jn.PeekTok();
                int ei = jn._i;
                bool match = false;
                foreach(var k in Words)
                {
                    if(k.Match(tok,ptok,ntok))
                    {

                        match = true;
                        var c = k.WorkCol;
                        EditArea.Select(s1+si,ei-si);
                        EditArea.SelectionColor = c;
                        break;
                    }
                }
                if(!match)
                {
                    var c = Color.DarkGray;
                    EditArea.Select ( s1 + si, ei - si );
                    EditArea.SelectionColor = c;
                }
                ptok = tok;
            }
            EditArea.Select(oi,ol);
        }
        public void AddText(string t)
        {
            //int si = EditArea.TextLength;
            AutoLight = false;
            EditArea.Text += t;
            EditArea.SelectionStart = EditArea.TextLength - 2;
            EditArea.ScrollToCaret();
            AutoLight = true;
            // Highlight(si,si+t.Length);

        }
        private bool AutoLight = true;
        public string ActiveKey = "";
        public int LastLine = -1, LastChar = -1;
        private void EditArea_TextChanged ( object sender, EventArgs e )
        {
            try
            {
                JR = new JointReflection(new JointApp(EditArea.Text, ""));
                if (!AutoLight) return;
                if (EditArea.TextLength == 0) return;
                if(EditArea.SelectionStart < LastChar)
                {
                    LastChar = EditArea.SelectionStart;
                    return;
                }
                LastChar = EditArea.SelectionStart;

                AutoLight = false;
                int cl = EditArea.GetLineFromCharIndex(EditArea.SelectionStart);
                if (EditArea.GetFirstCharIndexOfCurrentLine() == EditArea.SelectionStart)
                {
                   
                    LastLine = cl - 1;
                    if (LastLine < EditArea.Lines.Length && LastLine >= 0)
                    {
                        if (true )
                        {
                            LastChar = EditArea.SelectionStart;
                            var aa = "";
                            var pl = EditArea.Lines[LastLine];
                            for (int i = 0; i < pl.Length; i++)
                            {
                                var cr = pl[i].ToString();

                                bool done = false;
                                switch (cr)
                                {
                                    case " ":
                                        aa += " ";
                                        break;
                                    case "  ":
                                        aa += "   ";
                                        break;
                                    case "\t":
                                        aa += "\t";
                                        break;
                                    default:
                                        done = true;
                                        break;
                                }
                                if (done)
                                {
                                    break;
                                }
                            }
                            if (aa != null && aa.Length > 0)
                            {
                                Clipboard.SetText(aa);
                                Paste("");
                            }
                            // EditArea.Lines[cl] = aa;
                            // EditArea.SelectionStart = EditArea.GetFirstCharIndexFromLine(cl) + aa.Length;

                        }
                    }
                }
                else
                {

                    LastLine = cl;
                    LastChar = EditArea.SelectionStart;

                    HighlightLine();
                }

                AutoLight = true;
            }catch(System.Exception ex)
            {
                
            }
        }

        private void HighlightLine()
        {
            int li = EditArea.GetFirstCharIndexOfCurrentLine();
            int ln = EditArea.GetLineFromCharIndex(li);

            if ( ln < EditArea.Lines.Length )
            {
                string gl = EditArea.Lines[ln];
                var jn = new JointNode(gl, "");
                // Console.WriteLine("GL="+gl);
                while(!jn.Eof)
                {
                    int si = jn._i;
                    var t = jn.GetTok();
                    int ei = jn._i;
                    int ci = EditArea.SelectionStart - li;

                    if(ci>=si && ci<=ei)
                    {
                        ActiveKey = t;
                        ActiveSI = li+si;
                        ActiveEI = li+ei;
                        //        Console.WriteLine("Key:"+ActiveKey);
                       
                        break;
                    }

                }
            }
        
            if ( EditArea.Lines[ ln ] != null && EditArea.Lines[ ln ].Length > 1 )
            {
                Highlight(li, li+EditArea.Lines[ln].Length);
            }
        }

        private ListBox IS = null;
        public void ChangeKey(string k)
        {
            
            if(ActiveKey!="")
            {

                AutoLight = false;
                EditArea.Select(ActiveSI,ActiveEI-ActiveSI);
                EditArea.SelectedText = k;

                //EditArea.

                HighlightLine();
                AutoLight = true;
                //HighlightLine();

                EditArea.SelectionStart = ActiveSI + k.Length;

            }

        }
        public void UpdateCodeComplete()
        {
            if(CC.IsDisposed)
            {
                CC = new CodeComplete() {JR = JR};

            }
            if ( ActiveKey == "" )
            {
                CC.Close();
                return;
            }
            int cx, cy;
            var p = EditArea.PointToScreen(EditArea.GetPositionFromCharIndex(EditArea.SelectionStart));
            cx = p.X+35;
            cy = p.Y-100;
            
            
            CC.ActiveKey = ActiveKey;
            CC.PrevKey = PrevKey;
            CC.UpdateReflection();
            CC.Update();
            CC.Location = new Point ( cx, cy );
            CC.Size = new Size ( 150, 250 );

        }
        public string GetWord(int i)
        {
            int ss = EditArea.SelectionStart;
            var t = EditArea.Text;
            var jn = new JointNode ( t, "" );
            int wc = 0;
            while ( !jn.Eof )
            {
               
                var w = jn.GetTok ( );
                if ( wc == i ) return w;
        
                    wc++;
         
            }
            return "";
        }
        public int CurrentWord()
        {

            int ss = EditArea.SelectionStart;
            var t = EditArea.Text;
            var jn = new JointNode(t, "");
            int wc = 0;
            while(!jn.Eof)
            {
                var _si = jn._i;
                var t2 = jn.GetTok();

                var _ei = jn._i;
                if(ss>=_si && ss<=_ei)
                {

                    return wc;
                }
             
                    wc++;
           
            }
            return wc;
        }
        public int WordCount()
        {
            var t = EditArea.Text;
            var jn = new JointNode(t, "");
            int wc = 0;
            while(!jn.Eof)

            {
               var t2= jn.GetTok();
          
                   wc++;
            
            }
            return wc;
        }
        public void Paste(string t)
        {
            AutoLight = false;
            EditArea.Paste();
            AutoLight = true;
            
            //HighlightDoc();
        }

        public string LastKey = "";
        public int CompleteOn = -1;
        public int CompleteWait = 1500;
        public bool ShownComplete = false;
        public string PrevKey = "";
        public JointReflection JR = null;
        private void timer1_Tick ( object sender, EventArgs e )
        {
            ActiveKey = GetWord(CurrentWord());
            PrevKey = GetWord(CurrentWord() > 1 ? CurrentWord() - 2 : 0);
            
            if(ActiveKey!=LastKey)
            {
                LastKey = ActiveKey;
                CompleteOn = Environment.TickCount + CompleteWait;
                ShownComplete = false; 
            }else
            {
                if ( Environment.TickCount > CompleteOn )
                {
                    if (!ShownComplete)
                    {
                        ShownComplete = true;
                        CC.JR = JR;
                        if(JR!=null)
                        {
                            CC.UpdateReflection();
                        }
                        UpdateCodeComplete();
                    }
                }

            }
           // UpdateCodeComplete ( );
        }

        private void cutToolStripMenuItem_Click ( object sender, EventArgs e )
        {
            EditArea.Cut();
        }

        private void clipboardToolStripMenuItem_Click ( object sender, EventArgs e )
        {

        }

        private void copyToolStripMenuItem_Click ( object sender, EventArgs e )
        {
            EditArea.Copy();
        }

        private void pastToolStripMenuItem_Click ( object sender, EventArgs e )
        {
            Paste("");
        }

        private void kryptonButton1_Click ( object sender, EventArgs e )
        {
            AutoLight = false;
            Highlight(0, EditArea.Text.Length);
            AutoLight = true;

        }
    }
    public class Keyword
    {
        public string Key = "";
        public string Prev = "";
        public string Next = "";
        public Color WorkCol = Color.Blue;
        public Color FailCol = Color.Red;
        public Keyword ( string key, Color work, params string[ ] other )
        {
            Key = key;
            WorkCol = work;
            if ( other.Length > 0 )
            {
                Prev = other[ 0 ];
            }
            if ( other.Length > 1 ) Next = other[ 1 ];

        }
        public bool Match ( string key, string p, string n )
        {
            
            if ( key == Key || Key == "~")
            {
                if ( Prev != "" && Prev != "~")
                {
                    if ( p != Prev ) return false;

                }
                if ( Next != "" && Next !="~")
                {
                    if ( n != Next ) return false;
                }
                return true;
            }
            return false;
        }
    }
    
    
}
